package me.yuzho.study.internal;

/** 测试学习内部类
 *  
 *  Q: 什么情况下需要使用常规内部类
 * @author yzhou-citrix
 *
 */
public class MyOuter {
    
    private int x = 100;
    private static int sx = 100;
    
    public static void staticOuterMethod() {
        System.out.println("staticOuterMethod is called");
        sx++;
    }
    
    public void outerMethod() {
        System.out.println("outerMethod is called");
        x++;
    }
    
    public MyInner getInner() {
        System.out.println("Get a new instance of Inner class");
        MyInner in = new MyInner();
        return in;
    }
    
    public StaticInner getStaticInner() {
        return new StaticInner();
    }
    
    /** 常规内部类没有static修饰，且定义在外部类类体中
     *  1. 常规内部类中的方法可以直接使用外部类的实例变量和实例方法
     *  2. 在常规内部类中可以直接用内部类创建对象
     * @author yzhou-citrix
     *
     */
    class MyInner {
        private String y = "Hello!";
        
        public void innerMethod() {
            System.out.println("innerMethod is called");
            
            System.out.println("Call outerMethod in innerMethod");
            outerMethod();
            
            System.out.println("Print outer's private variable x: " + MyOuter.this.x);
            System.out.println("Print inner's private variable y: " + this.y);
        }
    }
    
    /** 静态内部类，使用static 修饰内部类
     * 1. 与静态内部方法相似，只能访问外部类的静态成员
     * 2. 不能访问外部类的实例变量，与实例方法，只能通过引用才能访问
     * 3. 不具有外部类的实例引用，不能使用this关键字来访问外部类的实例成员，可以访问外部类的静态成员
     * @author yzhou-citrix
     *
     */
     static class StaticInner {
        
        private String sy = "Hello!";
        
        public void innerMethod() {
            System.out.println("innerMethod is called");
            
            // outerMethod();  //不能调用外部类的方法
            //System.out.println(MyOuter.this.x); // 不能使用this关键字来访问外问实例
            
            System.out.println("Call staticOuterMethod in innerMethod");
            staticOuterMethod();
            
            System.out.println("Print outer's static variable sx: " + sx);
            System.out.println("Print inner's private variable sy: " + this.sy);
        }
     }
     
     private int size = 5, y = 7;
     
     public Object makeInner(int localVar) {
         final int finalLocalVar = localVar;
         
         /** 局部内部类
         * @author yzhou-citrix
         *
         */
        class MyInner {
             int y = 4;

            @Override
            public String toString() {
                // TODO Auto-generated method stub
                return String.format("Outer size: %d, Outer y: %d, Inner y: %d, final local: %d, local: %d", 
                        size, MyOuter.this.y, y, finalLocalVar, localVar);
            }
         }
        
        return new MyInner();
     }
     
     public Object makeAnoyInner(int localVar) {
         final int finalLocalVar = localVar;
         
         /**匿名内部类
         * @author yzhou-citrix
         *
         */
        return new Object() {
             int y = 4;

            @Override
            public String toString() {
                // TODO Auto-generated method stub
                return String.format("Outer size: %d, Outer y: %d, Inner y: %d, final local: %d, local: %d", 
                        size, MyOuter.this.y, y, finalLocalVar, localVar);
            }
         };
     }

}
